package com.song.ejf.dao;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.song.ejf.page.Page;

/** 统一数据访问接口实现 */
@SuppressWarnings({ "rawtypes", "unchecked" })
@Repository("baseDao")
public class BaseDAOImpl extends HibernateDaoSupport implements BaseDAO {

	@Autowired
	@Qualifier("sessionFactory")
	public void setSessionFactory1(SessionFactory sessionFactory) {
		super.setSessionFactory(sessionFactory);
	}

	/** 统计指定类的所有持久化对象 */
	public int countAll(String clazz) {
		final String hql = "select count(*) from " + clazz + " as a";
		Long count = (Long) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException {
						Query query = session.createQuery(hql);
						query.setMaxResults(1);
						return query.uniqueResult();
					}
				});
		return count.intValue();
	}

	/** 统计指定类的查询结果 */
	public int countQuery(String hql) {
		final String counthql = hql;
		Long count = (Long) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException {
						Query query = session.createQuery(counthql);
						query.setMaxResults(1);
						return query.uniqueResult();
					}
				});
		return count.intValue();
	}

	/** 删除指定ID的持久化对象 */
	public void delById(Class clazz, Serializable id) {
		getHibernateTemplate().delete(getHibernateTemplate().load(clazz, id));
	}

	/** 装载指定类的所有持久化对象 */
	public List listAll(String clazz) {
		return getHibernateTemplate().find(
				"from " + clazz + " as a order by a.id desc");
	}

	/** 分页装载指定类的所有持久化对象 */
	public List listAll(String clazz, int pageNo, int pageSize) {
		final int pNo = pageNo;
		final int pSize = pageSize;
		final String hql = "from " + clazz + " as a order by a.id desc";
		List list = getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException {
				Query query = session.createQuery(hql);
				query.setMaxResults(pSize);
				query.setFirstResult((pNo - 1) * pSize);
				List<Object> result = query.list();
				if (!Hibernate.isInitialized(result))
					Hibernate.initialize(result);
				return result;
			}
		});
		return list;
	}

	/** 加载指定ID的持久化对象 */
	public Object loadById(Class clazz, Serializable id) {
		return getHibernateTemplate().get(clazz, id);
	}

	/** 加载满足条件的持久化对象 */
	public Object loadObject(String hql) {
		final String hql1 = hql;
		Object obj = null;
		List list = getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException {
				Query query = session.createQuery(hql1);
				return query.list();
			}
		});
		if (list.size() > 0)
			obj = list.get(0);
		return obj;
	}

	/** 查询指定类的满足条件的持久化对象 */
	public List querySQL(String hql) {
		final String hql1 = hql;
		return getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException {
				Query query = session.createSQLQuery(hql1);
				return query.list();
			}
		});
	}

	/** 查询指定类的满足条件的持久化对象 */
	public List query(String hql) {
		final String hql1 = hql;
		return getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException {
				Query query = session.createQuery(hql1);
				return query.list();
			}
		});
	}

	/* 执行sql语句 */
	public int executeSQL(String sql) {
		SQLQuery query = this.getSession().createSQLQuery(sql);
		return query.executeUpdate();
	}

	/** 分页查询指定类的满足条件的持久化对象 */
	public List<Object> query(String hql, int pageNo, int pageSize) {
		final int pNo = pageNo;
		final int pSize = pageSize;
		final String hql1 = hql;
		return getHibernateTemplate().executeFind(new HibernateCallback() {
			public Object doInHibernate(Session session)
					throws HibernateException {
				Query query = session.createQuery(hql1);
				query.setMaxResults(pSize);
				query.setFirstResult((pNo - 1) * pSize);
				List<Object> result = query.list();
				if (!Hibernate.isInitialized(result))
					Hibernate.initialize(result);
				return result;
			}
		});
	}

	/** 保存或更新指定的持久化对象 */
	@Transactional
	public void saveOrUpdate(Object obj) {
		this.getHibernateTemplate().saveOrUpdate(obj);
	}

	/** 条件更新数据 */
	public int update(String hql) {
		final String hql1 = hql;
		return ((Integer) getHibernateTemplate().execute(
				new HibernateCallback() {
					public Object doInHibernate(Session session)
							throws HibernateException {
						Query query = session.createQuery(hql1);
						return query.executeUpdate();
					}
				})).intValue();
	}

	/* 分页查询 */
	public Page pageQuery(Page page, String hql, String sql) {
		List<Object> list = null;
		Session session = getSession();
		page.setTotal(this.getAllNum(sql));// 给工具类PageCommon赋予记录总数
		Query query = session.createQuery(hql.toString());
		query.setFirstResult(page.getStartIndex()).setMaxResults(
				page.getPageSize()); // 设置开始标记和结束标记
		list = query.list();
		page.setResultList(list);
		return page;
	}

	/**
	 * 获取总记录数
	 * 
	 * @return
	 */
	private int getAllNum(String hql) {
		Session session = getSession();
		Long t = (Long) session.createQuery(hql.toString()).uniqueResult();
		if (t != null)
			return t.intValue();
		return 0;
	}

	public Session getSessions() {
		return this.getSession();
	}

	/**
	 * 关联查询用 可自定义结果集. 返回结果集的key为大写字母。如果写小写取不出来值。
	 */
	@Override
	public List<Map<String, String>> executeSqlQuery(String sql) {
		return (List<Map<String, String>>) getSession().createSQLQuery(sql)
				.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP).list();
	}
	/**
	 *  sql 分页
	 * querySql 
	 * countSql 
	 * order 
	 */
	@Override
	public void sqlPageQuery(Page page, String selectSql, String mainSql,String order,Map<String, String> paraMap) throws Exception{
		Session session = getSession();
		Query selQuery = session.createSQLQuery(selectSql + " from (" +  mainSql + order + ")").setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		selQuery.setFirstResult(page.getStartIndex());
		selQuery.setMaxResults(page.getPageSize());
		Query countQuery = session.createSQLQuery("select count(*) from (" + mainSql + ")");
		if(paraMap != null && paraMap.size() > 0){
			for (String key : paraMap.keySet()) {
				String temp = paraMap.get(key);
				if(StringUtils.isNotBlank(temp)){
					selQuery.setParameter(key, temp);
					countQuery.setParameter(key, temp);
				}
			}
		}
		BigDecimal count = (BigDecimal)countQuery.uniqueResult();
		page.setTotal(count.intValue());
		page.setResultList(selQuery.list());
	}

	@Override
	public List<Map<String, String>> sqlQuery(String mainSql,Map<String, String> paraMap) throws Exception {
		Session session = getSession();
		Query selQuery = session.createSQLQuery(mainSql).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		if(paraMap != null && paraMap.size() > 0){
			for (String key : paraMap.keySet()) {
				String temp = paraMap.get(key);
				if(StringUtils.isNotBlank(temp)){
					selQuery.setParameter(key, temp);
				}
			}
		}
		return (List<Map<String, String>>)selQuery.list();
	}

	@Override
	public boolean exeQuery(String mainSql, Map<String, String> paraMap) throws Exception{
		Session session = getSession();
		Query selQuery = session.createSQLQuery(mainSql).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		if(paraMap != null && paraMap.size() > 0){
			for (String key : paraMap.keySet()) {
				String temp = paraMap.get(key);
				if(StringUtils.isNotBlank(temp)){
					selQuery.setParameter(key, temp);
				}
			}
		}
		selQuery.executeUpdate();
		return true;
	}
}